import * as THREE from 'three'
import {useLayoutEffect, useMemo, useEffect, useRef, Suspense} from 'react'
import { Canvas } from '@react-three/fiber'
import { Physics, RigidBody } from '@react-three/rapier'
import {
    KeyboardControls,
    useGLTF,
    useBoxProjectedEnv,
    Preload,
    AdaptiveDpr, Fisheye
} from '@react-three/drei'
import Controller, {EcctrlJoystick, EcctrlAnimation} from 'ecctrl'
import { useControls } from 'leva'
import UserModel from './UserModel'
import { Perf } from 'r3f-perf'

export default function HomePage() {
    useGLTF.preload('/court.glb');
    useGLTF.preload('/ghost_w_tophat-transformed.glb');
    // 使用useFrame钩子在每一帧更新调试对象
    return (<div style={{width: '100%', height: '100%'}}>
        <ThreeComponents />
        <EcctrlJoystick joystickBaseProps={{ receiveShadow: true }}/>
    </div>);
}

function UserControls() {
    const keyboardMap = [
        { name: 'forward', keys: ['ArrowUp', 'KeyW'] },
        { name: 'backward', keys: ['ArrowDown', 'KeyS'] },
        { name: 'leftward', keys: ['ArrowLeft', 'KeyA'] },
        { name: 'rightward', keys: ['ArrowRight', 'KeyD'] },
        { name: 'jump', keys: ['Space'] },
        { name: 'run', keys: ['Shift'] },
        { name: 'action1', keys: ['1'] },
        { name: 'action2', keys: ['2'] },
        { name: 'action3', keys: ['3'] },
        { name: 'action4', keys: ['KeyF'] }
    ]
    const path = '/player/Demon.glb'
    let {scene} = useGLTF(path)
    const animationSet = {
        idle: 'CharacterArmature|Idle',
        walk: 'CharacterArmature|Walk',
        run: 'CharacterArmature|Run',
        jump: 'CharacterArmature|Jump',
        jumpIdle: 'CharacterArmature|Jump_Idle',
        jumpLand: 'CharacterArmature|Jump_Land',
        fall: 'CharacterArmature|Duck', // This is for falling from high sky
        action1: 'CharacterArmature|Wave',
        action2: 'CharacterArmature|Death',
        action3: 'CharacterArmature|HitReact',
        action4: 'CharacterArmature|Punch'
    }
    return (<RigidBody colliders={false} type="dynamic" enabledRotations={[false, false, false]}>
        <KeyboardControls map={keyboardMap}>
            <Controller animated followLight capsuleHalfHeight={0.4} capsuleRadius={0.3}>
                <EcctrlAnimation characterURL={path} animationSet={animationSet}>
                    <UserModel />
                </EcctrlAnimation>
            </Controller>
        </KeyboardControls>
    </RigidBody>)
}

function GlobalLight() {
    return (
        <>
            <directionalLight
                intensity={0.7}
                color={'#FFFFED'}
                castShadow
                shadow-bias={-0.0004}
                position={[-20, 20, 20]}
                shadow-camera-top={20}
                shadow-camera-right={20}
                shadow-camera-bottom={-20}
                shadow-camera-left={-20}
            />
            <ambientLight intensity={0.2} />
        </>
    )
}

function ThreeComponents() {
    return (
        <Canvas shadows fallback={<div>Sorry no WebGL supported!</div>}  dpr={[1, 2]} gl={{ alpha: false }} camera={{ position: [-2, 1, 7], fov: 50 }}>
            <Perf position="top-left" minimal />
            {/*<Fisheye zoom={0.4}>*/}
                <color attach="background" args={['#f6d186']}/>
                {/*  背景 */}
                {/*<hemisphereLight intensity={1}/>*/}
                {/*/!*  半球光 *!/*/}
                {/*<fog attach="fog" args={['purple', 0, 130]}/>*/}
                {/*  雾气 */}
                <GlobalLight />
                <Physics timeStep="vary" debug={true}>
                    <UserControls/>
                    <Floor/>
                </Physics>
                {/* 预加载可见对象 */}
                <Preload/>
                {/* 允许暂时降低视觉质量以换取更多性能，例如当相机移动时 */}
                <AdaptiveDpr pixelated/>
            {/*</Fisheye>*/}
        </Canvas>
    )
}

// 地板
function Floor() {
    const { nodes, materials } = useGLTF('/court.glb')
    const { scale} = useControls({ scale: { value: 70, min: 0, max: 100 } })
    const projection = useBoxProjectedEnv([0, 0, 0], [scale, scale, scale])
    return (<RigidBody name="地板" type="fixed" colliders="trimesh" position={[0, 0, 0]}>
        <mesh receiveShadow position={[-13.68, -0.467, 17.52]} scale={0.1}
              geometry={nodes.GymFloor_ParquetShader_0.geometry} dispose={null}>
            <meshStandardMaterial
                map={materials.ParquetShader.map}
                normalMap={materials.ParquetShader.normalMap}
                normalMap-encoding={THREE.LinearEncoding}
                {...projection}
            />
        </mesh>
    </RigidBody>)
}
